#pragma once

#include <memory>
#include "stream/IOpenable.h"

namespace stream {

template<typename Wrapper>
class Iterator {
public:
    static Iterator End;

    Iterator(const Wrapper * wrapper) :_wrapper(wrapper) {}
    virtual ~Iterator(){}

    Iterator & operator ++(){
        _wrapper->reader()->next();
        return *this;
    }
    typename Wrapper::reader_type::record_type operator *() const {
        return _wrapper->reader()->current();
    }
    bool operator != (const Iterator & other) const {
        return _wrapper->reader()->hasNext();
    }
private:
    const Wrapper * _wrapper;
};
template<typename Wrapper> 
Iterator<Wrapper> Iterator<Wrapper>::End(nullptr);




template<typename R>
class ReaderWrapper : public IOpenable {
public:
    typedef R reader_type;

	explicit ReaderWrapper(std::shared_ptr<R> reader)
    : _reader(reader)
    {
    }
	~ReaderWrapper() override{
    }

	virtual Iterator<ReaderWrapper> begin() const {
        return Iterator<ReaderWrapper>(this);
    }
	virtual Iterator<ReaderWrapper> end() const {
        return Iterator<ReaderWrapper>::End;
    }

	std::shared_ptr<R> reader() const {
        return _reader;
    }
protected:
	bool _open() override {
	    return _reader->open();
    }
	void _close() override{
	    _reader->close();
    }

private:
	std::shared_ptr<R> _reader;
};
}//end namespace stream
